package com.youkeyi.ddy.cloud.application.system.login.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.youkeyi.ddy.cloud.application.system.login.dto.LoginDto;
import com.youkeyi.ddy.cloud.application.system.login.service.LoginService;
import com.youkeyi.ddy.cloud.common.api.basic.pub.annex.PublicAnnexCloudService;
import com.youkeyi.ddy.cloud.common.api.basic.pub.annex.dto.PublicAnnexListCloudDto;
import com.youkeyi.ddy.cloud.common.api.basic.pub.annex.dto.PublicAnnexListItemCloudDto;
import com.youkeyi.ddy.cloud.common.api.basic.pub.annex.param.PublicAnnexQueryCloudParam;
import com.youkeyi.ddy.cloud.common.api.basic.pub.auth.PublicAuthCloudService;
import com.youkeyi.ddy.cloud.common.api.basic.pub.auth.dto.PublicAuthListCloudDto;
import com.youkeyi.ddy.cloud.common.api.basic.pub.auth.dto.PublicAuthListItemCloudDto;
import com.youkeyi.ddy.cloud.common.api.basic.pub.auth.param.PublicAuthQueryCloudParam;
import com.youkeyi.ddy.cloud.common.api.basic.pub.corp.PublicCorpCloudService;
import com.youkeyi.ddy.cloud.common.api.basic.pub.corp.dto.PublicCorpListCloudDto;
import com.youkeyi.ddy.cloud.common.api.basic.pub.corp.dto.PublicCorpListItemCloudDto;
import com.youkeyi.ddy.cloud.common.api.basic.pub.corp.param.PublicCorpQueryCloudParam;
import com.youkeyi.ddy.cloud.common.api.basic.pub.mapping.PublicMappingCloudService;
import com.youkeyi.ddy.cloud.common.api.basic.pub.mapping.dto.PublicMappingListCloudDto;
import com.youkeyi.ddy.cloud.common.api.basic.pub.mapping.dto.PublicMappingListItemCloudDto;
import com.youkeyi.ddy.cloud.common.api.basic.pub.mapping.param.PublicMappingQueryCloudParam;
import com.youkeyi.ddy.cloud.common.api.basic.pub.menu.PublicMenuCloudService;
import com.youkeyi.ddy.cloud.common.api.basic.pub.menu.dto.PublicMenuListCloudDto;
import com.youkeyi.ddy.cloud.common.api.basic.pub.menu.dto.PublicMenuListItemCloudDto;
import com.youkeyi.ddy.cloud.common.api.basic.pub.menu.param.PublicMenuQueryCloudParam;
import com.youkeyi.ddy.cloud.common.api.basic.pub.position.PublicPositionCloudService;
import com.youkeyi.ddy.cloud.common.api.basic.pub.position.dto.PublicPositionListCloudDto;
import com.youkeyi.ddy.cloud.common.api.basic.pub.position.dto.PublicPositionListItemCloudDto;
import com.youkeyi.ddy.cloud.common.api.basic.pub.position.param.PublicPositionQueryCloudParam;
import com.youkeyi.ddy.cloud.common.api.basic.pub.user.PublicUserCloudService;
import com.youkeyi.ddy.cloud.common.api.basic.pub.user.dto.PublicUserListCloudDto;
import com.youkeyi.ddy.cloud.common.api.basic.pub.user.dto.PublicUserListItemCloudDto;
import com.youkeyi.ddy.cloud.common.api.basic.pub.user.param.PublicUserQueryCloudParam;
import com.youkeyi.ddy.cloud.common.constant.YoukeyiDdyApplicationSystemConstant;
import com.youkeyi.ddy.cloud.common.constant.YoukeyiDdyCloudBasicPublicConstant;
import com.youkeyi.ddy.cloud.common.context.entity.SystemContextEntity;
import com.youkeyi.ddy.cloud.common.utils.RedisUtils;
import com.youkeyi.ddy.cloud.common.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * LoginServiceImpl
 *
 * @Author liuxiawang
 * @Date 2024/4/23 4:04 PM
 * @Location shenzhen.china
 */
@Slf4j
@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private PublicUserCloudService publicUserCloudService;
    @Autowired
    private PublicPositionCloudService publicPositionCloudService;
    @Autowired
    private PublicMappingCloudService publicMappingCloudService;
    @Autowired
    private PublicAuthCloudService publicAuthCloudService;
    @Autowired
    private PublicMenuCloudService publicMenuCloudService;
    @Autowired
    private PublicCorpCloudService publicCorpCloudService;
    @Autowired
    private PublicAnnexCloudService publicAnnexCloudService;

    @Override
    public LoginDto login(String account, String password, String token, String fromType) {
        LoginDto loginDto = new LoginDto();

        PublicUserQueryCloudParam userQueryCloudParam = new PublicUserQueryCloudParam();
        if ("minApp".equals(fromType) || "official".equals(fromType)) {
            userQueryCloudParam.setPhones(Collections.singletonList(account));
        } else {
            userQueryCloudParam.setAccounts(Collections.singletonList(account));
        }
        userQueryCloudParam.setNeedPosition(Boolean.TRUE);
        PublicUserListCloudDto userDtos = publicUserCloudService.query(userQueryCloudParam);
        if (userDtos != null && CollectionUtils.isNotEmpty(userDtos.getRows())) {
            PublicUserListItemCloudDto user = userDtos.getRows().get(0);

            // 查询主体
            PublicCorpQueryCloudParam corpQueryCloudParam = new PublicCorpQueryCloudParam();
            corpQueryCloudParam.setCorpPrimaryKeys(Collections.singletonList(user.getCorpKey()));
            PublicCorpListCloudDto corpDtos = publicCorpCloudService.query(corpQueryCloudParam);
            if (null == corpDtos || CollectionUtils.isEmpty(corpDtos.getRows())) {
                loginDto.setErrorMessage("主体不存在");
                return loginDto;
            }
            PublicCorpListItemCloudDto corp = corpDtos.getRows().get(0);
            // 如果是续费主体，需要判断主体使用期是否过期
            if (YoukeyiDdyCloudBasicPublicConstant.PUBLIC_CORP_AUTH_TYPE_1.value().equals(corp.getAuthType())) {
                if (corp.getExpiredTime() != null && corp.getExpiredTime() < System.currentTimeMillis()) {
                    loginDto.setErrorMessage("主体使用期已过期");
                    return loginDto;
                }
            }

            List<String> logoKeys = new ArrayList<>();
            if (StringUtils.isNotBlank(corp.getLeftLogo())) {
                logoKeys.add(corp.getLeftLogo());
            }
            if (StringUtils.isNotBlank(corp.getRightLogo())) {
                logoKeys.add(corp.getRightLogo());
            }
            if (CollectionUtils.isNotEmpty(logoKeys)) {
                Map<String, String> logoMap = new HashMap<>();
                PublicAnnexQueryCloudParam annexQueryCloudParam = new PublicAnnexQueryCloudParam();
                annexQueryCloudParam.setAnnexPrimaryKeys(logoKeys);
                PublicAnnexListCloudDto annexDtos = publicAnnexCloudService.query(annexQueryCloudParam);
                if (null != annexDtos && CollectionUtils.isNotEmpty(annexDtos.getRows())) {
                    logoMap.putAll(annexDtos.getRows().stream().collect(Collectors.toMap(PublicAnnexListItemCloudDto::getAnnexPrimaryKey, PublicAnnexListItemCloudDto::getUrl, (k1, k2) -> k1)));
                }
                loginDto.setLeftLogo(logoMap.get(corp.getLeftLogo()));
                loginDto.setRightLogo(logoMap.get(corp.getRightLogo()));
            }

            // 校验是否账户是否删除
            if (user.getIsDeleted().equals(YoukeyiDdyCloudBasicPublicConstant.SYSTEM_YES_OR_NO_YES.value())) {
                loginDto.setErrorMessage("用户不存在");
                return loginDto;
            }

            // 密码通过密码加密的私钥进行md5的加密（不可逆）
            if (!"minApp".equals(fromType) && !"minAppAuth".equals(fromType) && !"official".equals(fromType)) {
                String encryptPassword = SecurityUtils.md5(password, user.getUserPrimaryKey());
                // 校验是否账户与密码一致
                if (!user.getPassWord().equals(encryptPassword)) {
                    loginDto.setErrorMessage("密码错误");
                    return loginDto;
                }
            }

            loginDto.setToken(token);
            loginDto.setUserPrimaryKey(user.getUserPrimaryKey());
            loginDto.setUserAccount(user.getAccount());
            loginDto.setCorpKey(user.getCorpKey());
            loginDto.setCorpType(corp.getType() != null ? corp.getType().toString() : null);
            loginDto.setCorpCategory(corp.getCategory() != null ? corp.getCategory().toString() : null);
            loginDto.setCorpTypeName(YoukeyiDdyCloudBasicPublicConstant.PUBLIC_CORP_TYPE.getName(corp.getType()));
            loginDto.setCorpCoordinate(corp.getCoordinate());
            loginDto.setIsRoot(user.getIsRoot());
            loginDto.setUserCode(user.getCode());
            loginDto.setName(user.getName());
            loginDto.setNickName(user.getNickName());
            loginDto.setPhone(user.getPhone());
            loginDto.setEmail(user.getEmail());
            loginDto.setAvatarUrl(user.getAvatarUrl());
            loginDto.setRemark(user.getRemark());
            loginDto.setPositionKey(CollectionUtils.isNotEmpty(user.getPositionKeys()) ? user.getPositionKeys().get(0) : null);
            loginDto.setPositionCode(CollectionUtils.isNotEmpty(user.getPositions()) ? user.getPositions().get(0).getCode() : null);
            loginDto.setPositionName(CollectionUtils.isNotEmpty(user.getPositions()) ? user.getPositions().get(0).getName() : null);
            loginDto.setOpenId(user.getOpenId());
            loginDto.setOfficialOpenId(user.getOfficialOpenId());
            loginDto.setUnionId(user.getUnionId());

            // 补充其他数据（部门、岗位、权限、菜单）
            if (CollectionUtils.isNotEmpty(user.getPositionKeys())) {
                String positionKey = user.getPositionKeys().get(0);
                PublicPositionQueryCloudParam positionQueryCloudParam = new PublicPositionQueryCloudParam();
                positionQueryCloudParam.setPositionPrimaryKeys(Collections.singletonList(positionKey));
                positionQueryCloudParam.setNeedOrganization(Boolean.TRUE);
                PublicPositionListCloudDto positionDtos = publicPositionCloudService.query(positionQueryCloudParam);
                if (null != positionDtos && CollectionUtils.isNotEmpty(positionDtos.getRows())) {
                    PublicPositionListItemCloudDto position = positionDtos.getRows().get(0);
                    loginDto.setOrganizationKey(position.getOrganizationKey());
                    loginDto.setOrganizationName(null != position.getOrganization() ? position.getOrganization().getName() : null);
                    loginDto.setAuthPrimaryKeys(position.getAuthKeys());

                    // 通过authKeys反查菜单keys
                    PublicMappingQueryCloudParam publicMappingQueryCloudParam = new PublicMappingQueryCloudParam();
                    publicMappingQueryCloudParam.setMappingType(YoukeyiDdyCloudBasicPublicConstant.PUBLIC_MAPPING_TYPE_MENU_AUTH.value());
                    publicMappingQueryCloudParam.setKeyType(YoukeyiDdyCloudBasicPublicConstant.PUBLIC_MAPPING_KEY_TYPE_TARGET.value());
                    publicMappingQueryCloudParam.setKeys(position.getAuthKeys());
                    PublicMappingListCloudDto publicMappingDtos = publicMappingCloudService.query(publicMappingQueryCloudParam);
                    if (null != publicMappingDtos && CollectionUtils.isNotEmpty(publicMappingDtos.getRows())) {
                        loginDto.setMenuPrimaryKeys(publicMappingDtos.getRows().stream().map(PublicMappingListItemCloudDto::getSourceKey).collect(Collectors.toList()));
                    }
                }
            }

            // 补充是根账号的情况 查询所有的auth根menu
            if (YoukeyiDdyCloudBasicPublicConstant.SYSTEM_YES_OR_NO_YES.value().equals(user.getIsRoot()) || 2 == user.getIsRoot()) {
                PublicAuthQueryCloudParam authQueryCloudParam = new PublicAuthQueryCloudParam();
                PublicAuthListCloudDto authDtos = publicAuthCloudService.query(authQueryCloudParam);
                if (null != authDtos && CollectionUtils.isNotEmpty(authDtos.getRows())) {
                    loginDto.getAuthPrimaryKeys().addAll(authDtos.getRows().stream().map(PublicAuthListItemCloudDto::getAuthPrimaryKey).collect(Collectors.toList()));
                }

                PublicMenuQueryCloudParam menuQueryCloudParam = new PublicMenuQueryCloudParam();
                PublicMenuListCloudDto menuDtos = publicMenuCloudService.query(menuQueryCloudParam);
                if (null != menuDtos && CollectionUtils.isNotEmpty(menuDtos.getRows())) {
                    loginDto.getMenuPrimaryKeys().addAll(menuDtos.getRows().stream().map(PublicMenuListItemCloudDto::getMenuPrimaryKey).collect(Collectors.toList()));
                }
            }

            // 登录成功
            // 1。查询用户数据
            // 2。查询用户员工、组织（部门数据）
            // 3。查询用户权限数据
            SystemContextEntity sce = new SystemContextEntity();
            sce.setFromType(fromType);
            sce.setUserPrimaryKey(user.getUserPrimaryKey());
            sce.setUserName(user.getName());
            sce.setUserPhone(user.getPhone());
            sce.setAccount(user.getAccount());
            sce.setIsRoot(user.getIsRoot() != null ? user.getIsRoot().toString() : "0");
            sce.setCorpPrimaryKey(user.getCorpKey());
            sce.setCorpType(corp.getType() != null ? corp.getType().toString() : null);
            sce.setAvatarUrl(user.getAvatarUrl());
            sce.setNickName(user.getNickName());
            sce.setOrganizationKey(loginDto.getOrganizationKey());
            sce.setOrganizationName(loginDto.getOrganizationName());
            sce.setPositionKey(loginDto.getPositionKey());
            sce.setPositionCode(loginDto.getPositionCode());
            sce.setPositionName(loginDto.getPositionName());
            sce.setAuthPrimaryKeys(JSON.toJSONString(loginDto.getAuthPrimaryKeys()));
            Map<String, String> claimsMap = JSONObject.parseObject(JSONObject.toJSONString(sce), Map.class);
            try {
                // 登录成功之后，将原来的公钥/私钥清除，并将用户数据扔进redis
                RedisUtils.addHashMapToJedis(YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_DB_INDEX, token, claimsMap, YoukeyiDdyApplicationSystemConstant.AUTH_REDIS_CACHE_SECONDS);
            } catch (Exception e) {
                log.error("将登录用户数据存入缓存失败！", e);
            }
        }
        return loginDto;
    }
}
